PROGRAMACIÓN
ORIENTADA A
ASPECTOS

“Un aspecto es una unidad modular que se disemina por la estructura de otras unidades funcionales” (Gregor Kickzales)

“La Programación Orientada a Aspectos trata con temas trasversales y descripciones, diseño e implementación de estos temas” (Karl Lieberherr)

“Los meta-objetos parecen ser un lugar natural para implementar aspectos” (Charlotte Pii Lunau)



Programación Orientada a Aspectos (POA)

Al diseñar un sistema software, nos vemos obligados a elegir un paradigma principal (o dimensión conceptual dominante) de tipo modular (objetual, funcional, procedimental, etc.). Es la llamada “tiranía de la descomposición dominante”. Pero hay fragmentos de código que están dispersos en los módulos del sistema y que constituyen unidades funcionales trasversales (cross-cutting concerns). Son los llamados “aspectos”. Un aspecto de un programa o código es una unidad modular del programa que está diseminada en otras unidades modulares del programa.

La POA −AOP en sus siglas en inglés− es un nuevo paradigma de programación cuyo objetivo es recoger en módulos adicionales centralizados esas funcionalidades trasversales. Un aspecto es una funcionalidad trasversal que se implementa de forma modular y separada del resto del sistema.

La POA no afecta a la funcionalidad principal de un sistema, sino a facetas de su comportamiento: temas, propiedades o áreas de tipo colateral o transversal, que afectan a todos los componentes de dicho sistema, independientemente de su estructura o dependencia funcional entre ellos. La web AOSD (Aspect Oriented Software Development) define la POA como “Un paradigma de programación en el que los temas transversales que impregnan un sistema son aislados y extraidos en módulos separados llamados aspectos”. La aplicación del paradigma de la POA consiste en:
Tipos de aspectos

Hay diferentes tipos o categorías de aspectos. Pueden ser de bajo o de alto nivel. Pueden ser de tipo funcional o no. Pueden ser de diseño o de implementación. Algunos ejemplos son: La persistencia −el almacenamiento y recuperación de datos de una aplicación en el almacenamiento secundario− es un ejemplo típico de tema trasversal o aspecto. Una aplicación se puede desarrollar sin considerar el tema de la persistencia y abordarla en una fase posterior. Este enfoque tiene la ventaja de que, si se cambia el tipo de almacenamiento, basta con cambiar solo el módulo de persistencia, sin necesidad de cambiar la funcionalidad del sistema. La misma ventaja se tiene con los otros aspectos.


Ventajas de la POA

La aplicación del paradima POA tiene muchas ventajas:
Implementación de la POA

La solución tradicional consiste en repetir el código correspondiente en los diferentes módulos que lo necesiten, porque no había forma de encapsular en un único módulo algo que atravesaba a múltiples módulos del sistema. El resultado era un código enmarañado.

Actualmente, la POA se implementa mediante los siguientes componentes:
  1. Un lenguaje base (de propósito general) que permita definir la funcionalidad básica.

  2. Uno o varios lenguajes orientados a aspectos, que pueden ser:

    1. Específicos.
      Son lenguajes especiales para tratar diferentes aspectos concretos en dominios también concretos. Estos lenguajes imponen normalmente restricciones en la utilización del lenguaje base para garantizar su correcta utilización. Ejemplos: COOL (Concurrent Object Oriented Language), RIDL (Reliable Interface Design Language), etc.

    2. Generales.
      Son lenguajes válidos para toda clase de aspectos. Son más abiertos y es responsabilidad del programador su correcta utilización. Ejemplos: AspectJ (una extensión de Java), AspectC++ (una extensión de C++), etc.

  3. Puntos de unión (Join Points).
    Se definen en la aplicación base e indican los lugares donde deben aplicarse los aspectos.

  4. Puntos de corte (PointCuts).
    Es el conjunto de condiciones necesarias para que se ejecute un módulo de aspecto en un punto de unión.

  5. Puntos de ejecución (Execution Points).
    Son los módulo que se ejecutan cuando se activa un punto de corte en un punto de unión.

  6. Consejos (advices).
    Son las acciones que se ejecutan en cada punto de unión y que se activan con los puntos de corte correspondientes.

  7. Tejedor (Weaver) de aspectos.
    Se encarga de entrelazar el lenguaje base con los lenguajes de aspectos a través de los puntos de unión, generando un programa completo. El entrelazamiento puede ser estático (en tiempo de compilación) o dinámico (en tiempo de ejecución).

Descomposición de un sistema por aspectos

Un sistema software admite varias descomposiciones posibles, según los diferentes aspectos que se quieran considerar. Pero, de acuerdo con la funcionalidad principal que se le desea asignar, existe una descomposición dominante.

Si la funcionalidad principal y las correspondientes a las de los aspectos se integraran en una única descomposición, el resultado sería un tanto caótico, pues el código de tratamiento de cada aspecto quedaría diseminado por todo el código, con la consiguiente complejidad resultante.

La solución a este problema consiste en:
  1. Sustituir la descomposición clásica de un sistema en bloques conceptuales (funciones, procedimientos, objetos, etc.) por la descomposición aspectual, en donde la descomposición clásica es realmente otro aspecto, aunque sea el principal.

  2. Programar de forma independiente el proceso de los aspectos, en forma de componentes o módulos, con el objetivo de conseguir más claridad.

  3. Enlazar el proceso principal con los procesos de los diferentes aspectos.

Historia de la POA

El paradigma de la POA ha sido el resultado de la convergencia de varias líneas de investigación independientes y que comenzaron con el principio fundamental de descomposición modular del software, cuyos pioneros fueron Edsger Dijkstra y David Parnas.
Implementación de Aspectos en MENTAL

Con MENTAL todo se simplifica y clarifica:
Ejemplos
  1. Queremos conocer cuantos valores sucesivos toma la variable x a lo largo de la ejecución de un programa.

    ⟨( (nvals := 0) // número de valores inicial

    (x=v → ( (nvals=0 ∨ (nvals > 0 ∧ (xvals(nvals) ≠ v))) →
    ((nvals = nvals+1)
    (xvals(nvals) = v) ) ) )⟩


  2. Queremos restringir todas las secuencias a que sean de una determinada longitud n como máximo.

    ⟨( ((x = ( x↓ )) ∧ (x# > n)) → // si x es una secuencia y de longitud > n

    ((m = x#) [x\[n+1…m] = θ] )⟩ // eliminar los sobrantes


  3. Estructura de procesos concurrentes.
    Los procesos p1 y p2 deben arrancarse simultáneamente cuando se cumple la condición k=1, y cuando finalicen ambos, debe ejecutarse el proceso p3.

    ⟨( (k = 1) → ((k = 0) ({p1 p2} p3)) )⟩

    La restauración de la variable k es importante para que no se vuelva a cumplir la condición.


Adenda

Técnicas relacionadas

Muchas técnicas de programación incluyen conceptos similares a los de la programación orientada a aspectos como:
Sistemas reflexivos

Un módulo reflexivo es un módulo que se sitúa en un nivel superior (nivel meta) desde el que observa lo que ocurre en el nivel base y toma decisiones. Puede incluso modificar el código base. También se denomina “reflexión computacional” [Maes, 1987]. En la reflexión computacional tradicional, un objeto del nivel base tiene como máximo un meta-objeto.


Programación adaptativa

Es una metodología de diseño y desarrollo de software orientado a objetos de tipo evolutivo, es decir, creciente, progresivo e incremental.

El diseño se realiza a partir de unas sucintas especificaciones iniciales, de tipo informal, en las que se separan los objetos y las operaciones. El objetivo es mantener un acoplamiento lo más ligero posible entre los objetos y las operaciones, de tal forma que las modificaciones de una parte tengan el mínimo impacto en las otras.

El software no se desarrolla directamente a nivel de objetos, sino a un nivel tal que se pueda adaptar fácilmente a una gran variedad de contextos. El resultado es un software más flexible, más compacto y más inteligible.

Un programa adaptativo consta de n partes a1, …, an, en donde cada parte ai expresa un aspecto lo más independiente posible del resto. El programa ejecutable se especifica mediante una función c de tipo combinatorio entre esas n partes: c(a1,…,an).

El grupo Demeter ha sido el pionero de la Programación Adaptativa. La llamada “ley de Demeter” se anunció en 1987. Esta ley fue mejorada posteriormente por Kart Lieberherr en el contexto de la Programación Orientada a Aspectos.

Actualmente se considera se considera la Programación Adaptativa como un caso especial de la Programación Orientada a Aspectos.


Programación Orientada a Temas (Subject-Oriented Programming)

Es una técnica de programación que complementa a la POO para resolver los problemas de interoperabilidad, cooperación e integración de aplicaciones.

Los sistemas se modularizan considerando inicialmente temas o aspectos, tanto de tipo estático como dinámico (detección y gestión de errores, persistencia, etc.). A partir de estos módulos se construyen los objetos y las aplicaciones. Los módulos de aspecto entran en acción con eventos del tipo “antes de” o “después de” una operación. Los “Puntos de Unión” se realizan, pues, a nivel de operación, frente al enfoque clásico, que son a nivel de sentencia.

La Programación Orientada a Temas fue iniciada en IBM por Harold Ossher y Hill Harrison.

La Programación Orientada a Temas se considera actualmente como una forma de implementación de la Programación Orientada a Aspectos.


Bibliografía